import Koa from 'koa'
import path from 'path'
import koaStatic from 'koa-static'
import router from './router'
import { ApolloServer } from 'apollo-server-koa'
import { PubSub } from 'apollo-server-koa'
import { EventEmitter } from 'events'
import typeDefs from './schema'
import resolvers from './controller/resolvers'
import WebSocket from 'ws';
import { Context } from './type'

export const pubsub = new PubSub()
export const channelMap: Map<WebSocket, string> = new Map()
export const channelSet: Set<string> = new Set()
export const emitter = new EventEmitter()
const graphqlServer = new ApolloServer({
  typeDefs,
  resolvers,
  subscriptions: {
    onConnect: (connectionParams, webSocket, context): Context => {
      const channel = Math.random().toString(36).substring(2, 15) // random channel name
      channelMap.set(webSocket, channel)
      channelSet.add(channel)
      return {
        channel,
      }
    },
    onDisconnect: (webSocket, context) => {
      const channel = channelMap.get(webSocket)
      if (channel) {
        channelMap.delete(webSocket)
        channelSet.delete(channel)
        emitter.emit('channelExit', channel)
        console.log(`Channel: ${channel} exited.`)
      }
    },
  },
})

export default () => {
  const app = new Koa()
  app.use(koaStatic(path.resolve(__dirname, '../www')))
  graphqlServer.applyMiddleware({ app })
  app.use(router.routes())
  const httpServer = app.listen(7002, '0.0.0.0')
  graphqlServer.installSubscriptionHandlers(httpServer)
  console.log(
    `🚀 Server ready at http://localhost:7002${graphqlServer.graphqlPath}`
  )
  console.log(
    `🚀 Subscriptions ready at ws://localhost:7002${graphqlServer.subscriptionsPath}`
  )
  return app
}
